package com.taoyi.mhouse.fragments;

import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;

import com.taoyi.mhouse.R;
import com.taoyi.mhouse.util.LocalDisplay;
import com.tempo.widget.LoadingView;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import in.srain.cube.views.ptr.PtrDefaultHandler;
import in.srain.cube.views.ptr.PtrFrameLayout;
import in.srain.cube.views.ptr.header.MaterialHeader;

/**
 * @author tempo
 *         on 2015/11/23.
 */
public abstract class LoadingFreshingFragment<T> extends BaseFragment {
    private PtrFrameLayout mPtrFrameLayout;
    private FrameLayout mContainer;
    private ResultState state=null;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
        mPtrFrameLayout = (PtrFrameLayout) inflater.inflate(R.layout.fragment_loading, container, false);
        mContainer = (FrameLayout) mPtrFrameLayout.findViewById(R.id.mContainer);
        initPtrFrameLayout();
        state=ResultState.Empty;
        return mPtrFrameLayout;
    }

    private void initPtrFrameLayout() {
        // header
        final MaterialHeader header = new MaterialHeader(getContext());
        int[] colors = getResources().getIntArray(R.array.google_colors);
        header.setColorSchemeColors(colors);
        header.setLayoutParams(new PtrFrameLayout.LayoutParams(-1, -2));
        header.setPadding(0, LocalDisplay.dp2px(15), 0, LocalDisplay.dp2px(10));
        header.setPtrFrameLayout(mPtrFrameLayout);

        mPtrFrameLayout.setLoadingMinTime(350);
        mPtrFrameLayout.setDurationToCloseHeader(220);
        mPtrFrameLayout.setHeaderView(header);
        mPtrFrameLayout.addPtrUIHandler(header);
        mPtrFrameLayout.setPinContent(true);
        mPtrFrameLayout.setPtrHandler(new PtrDefaultHandler() {
            @Override
            public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) {
                return super.checkCanDoRefresh(frame, getCheckRefreshView(frame, content), header);
            }

            @Override
            public void onRefreshBegin(final PtrFrameLayout frame) {
                loadData(new LoadingCallback());
            }
        });

    }
    private boolean refreshOnResume=false;
    public void onFragmentSelected() {
        if(fragmentState==FragmentState.EMPTY||fragmentState==FragmentState.OnDestroy){
            refreshOnResume=true;
        }else{
            refreshOnResume=false;
            mPtrFrameLayout.postDelayed(new Runnable() {
                @Override
                public void run() {
                    mPtrFrameLayout.autoRefresh(false);
                }
            }, 100);
        }
    }

    public View getCheckRefreshView(PtrFrameLayout frame, View content) {
        View realView = ((ViewGroup)  content).getChildAt(0);
        return realView;
    }

    public abstract void loadData(LoadingCallback callback);

    public abstract View getSuccessView(View parent, T data);



    @Override
    public void onResume() {
        super.onResume();
        if(refreshOnResume){
            onFragmentSelected();
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        fragmentState=FragmentState.OnDestroy;
        clearData();
    }

    protected abstract void clearData();

    public class LoadingCallback {
        public void setResult(ResultState resultState, T data) {
            switch (resultState) {
                case Success:
                    switchState(ResultState.Success, data);
                    break;
                case Error:
                    switchState(ResultState.Error, null);
                    break;
                case Empty:
                    switchState(ResultState.Empty, null);
                    break;
            }
        }
    }

    protected void switchState(ResultState state, T data) {
        View target = null;
        Context context=getContext();
        if(context==null){
            /**\
             * fragment is dettached from activity
             */
            return ;
        }
        if(this.state==ResultState.Success&&state!=ResultState.Success){
            mPtrFrameLayout.refreshComplete();
            return;
        }
        switch (state) {
            case Empty:
                target = getEmptyView(context);
                break;
            case Error:
                target = getErrorView(context);
                break;
            case Success:
                target = getSuccessView(mContainer, data);
                break;
            default:
                throw new IllegalArgumentException("undefined type");
        }
        this.state=state;
        mContainer.removeAllViews();
        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
        target.setLayoutParams(params);
        mContainer.addView(target);
        mPtrFrameLayout.refreshComplete();
    }

    private View getErrorView(Context context) {
        View errorView = LayoutInflater.from(context).inflate(com.tempo.widget.R.layout.loading_error, null);
        errorView.findViewById(com.tempo.widget.R.id.btn_loadmore).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                stateRefresh();
            }
        });
        return errorView;
    }

    private View getEmptyView(Context context) {

        View empty = LayoutInflater.from(context).inflate(com.tempo.widget.R.layout.loading_empty, null);

        return empty;
    }

    public enum ResultState {
        Success, Error, Empty
    }

    private void stateRefresh() {
        if (!mPtrFrameLayout.isRefreshing()) {
            try {
                mPtrFrameLayout.refreshComplete();
                Method method = mPtrFrameLayout.getClass().getDeclaredMethod("tryToNotifyReset");
                method.setAccessible(true);
                Boolean result = (Boolean) method.invoke(mPtrFrameLayout);
                mPtrFrameLayout.autoRefresh(false);
                //todo :in some case this method is not call really,so something must be do later
//                if(!result){
//                    new Handler().postDelayed(new Runnable() {
//                        @Override
//                        public void run() {
//                            try{
//                                mPtrFrameLayout.refreshComplete();
//                                Method method = mPtrFrameLayout.getClass().getDeclaredMethod("tryToNotifyReset");
//                                method.setAccessible(true);
//                                Boolean result = (Boolean) method.invoke(mPtrFrameLayout);
//                                mPtrFrameLayout.autoRefresh(false);
//                            }catch(Exception e){
//                                e.printStackTrace();
//                            }
//                        }
//                    },500);
//                }
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }
}
